package com.gateway.security.endpoint;

import com.gateway.common.utils.JsonUtils;
import com.gateway.security.config.SecurityConfig;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancedExchangeFilterFunction;
import org.springframework.util.CollectionUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriBuilder;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.Map;
import java.util.function.Function;

/**
 * @program: api-gateway
 * @description:
 * @author: YuKai Fan
 * @create: 2025/2/11 20:22
 **/
public class UaaTokenEndpointService extends CacheTokenEndpointService {

    private final WebClient webClient;

    public UaaTokenEndpointService(WebClient webClient) {
        this.webClient = webClient;
    }

    public UaaTokenEndpointService(LoadBalancedExchangeFilterFunction function) {
        this.webClient = WebClient.builder()
                .filter(function)
                .build();
    }


    @Override
    protected Mono<Map<String, Object>> getClaimsByToken(String token, SecurityConfig.Config config) {
        return webClient.get()
                .uri(config.getUri(), uriBuilder -> {
                    UriBuilder builder = uriBuilder.queryParam(config.getParamName(), token);
                    Map<String, String> queryParams = config.getQueryParams();
                    if (!CollectionUtils.isEmpty(queryParams)) {
                        queryParams.forEach(builder::queryParam);
                    }
                    return builder.build();
                })
                .retrieve()
                .bodyToMono(String.class)
                .flatMap((Function<String, Mono<Map<String, Object>>>) body -> Mono.justOrEmpty(JsonUtils.toObjectMap(body)))
                .defaultIfEmpty(Map.of());
    }

    private UriBuilder buildParam(UriBuilder uriBuilder, SecurityConfig.Config config, String token) {
        uriBuilder.queryParam(config.getTokenName(), token);
        Map<String, String> queryParams = config.getQueryParams();
        if (CollectionUtils.isEmpty(queryParams)) {
            return uriBuilder;
        }
        queryParams.forEach(uriBuilder::queryParam);
        return uriBuilder;
    }
}
